const fs = require('fs')
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const tee = require('@babel/types');
const generator = require("@babel/generator").default;


function main(text, pageOfText) {
    var ast = parser.parse(text.toString(), {
        sourceType: "module"
    })
    var JSfeatures = {};

    // 结构树
    var listSt = [];

    var haveIn = [];

    var letbeRuue = -1;

    var yhhDict = {}

    function cbb() {
        haveIn.push(0)
        if ('cbbFunctionDeclaration' in JSfeatures) {
            JSfeatures['cbbFunctionDeclaration'] += 1
        } else {
            JSfeatures['cbbFunctionDeclaration'] = 1
        }
        ;

        letbeRuue += 1;
        if (listSt[letbeRuue] == undefined) {
            listSt.push(0);
        } else {
            listSt[letbeRuue] += 1;
        }
    }

    function cbbl(path, lenAbot, findType) {

        var getCbbiYhh = path.scope.getOwnBinding('cbbiyhh');
        if (getCbbiYhh != undefined) {
            getCbbiYhh.referencePaths.forEach(function (px) {
                var path = px.parentPath;
                let coLid = path.node.arguments[0].value;
                let renWu = path.node.arguments[1].value;
                let evalCmd = path.node.arguments[2].value;
                let intOfJs = path.node.arguments[3].value;
                let hans = path + ""
                yhhDict[coLid] = {"renWu": renWu, "evalCmd": evalCmd};
                if (path.parentPath.isExpressionStatement()) {
                    if (path.key == 0 && path.container.length != 1) {
                        yhhDict[coLid].commentOfme = [path.parentPath.key, path.parentPath.container.length - 1, path.parentPath.container[path.parentPath.key + 1].type, 0, generator(path.parentPath.container[path.parentPath.key + 1]).code];
                    } else {
                        if (generator(path.parentPath.container[path.parentPath.key - 1]).code.indexOf('cbbiyhh') == -1) {
                            yhhDict[coLid].commentOfme = [path.parentPath.key, path.parentPath.container.length - 1, path.parentPath.container[path.parentPath.key - 1].type, 1, generator(path.parentPath.container[path.parentPath.key - 1]).code];
                        } else {
                            yhhDict[coLid].commentOfme = [path.parentPath.key - 1, path.parentPath.container.length - 2, path.parentPath.container[path.parentPath.key - 2].type, 1, generator(path.parentPath.container[path.parentPath.key - 2]).code];
                        }
                    }
                } else {
                    if (path.key == 0 && path.container.length != 1) {
                        yhhDict[coLid].commentOfme = [path.key, path.container.length - 1, path.container[path.key + 1].type, 0, generator(path.container[path.key + 1]).code];
                    } else {
                        yhhDict[coLid].commentOfme = [path.key, path.container.length - 1, path.container[path.key - 1].type, 1, generator(path.container[path.key - 1]).code];
                    }
                }
                ;
                let funTopar = path.findParent(function (p) {
                    if (p.isFunctionDeclaration() || p.isFunctionExpression()) {
                        return true;
                    }
                });

                let findBiianLian = 0;
                let ncv = [];
                funTopar.traverse({
                    Identifier(p) {
                        findBiianLian += 1

                        if (p.node.name == intOfJs && (p.parentPath + '') == hans) {
                            p.stop()
                            console.log('')
                        } else if (p.node.name == intOfJs) {
                            ncv.push(findBiianLian)
                        }
                        ;
                    }
                });

                yhhDict[coLid].commentOfme.push(ncv[ncv.length - 1])
                findBiianLian = 0
                ncv = []
                yhhDict[coLid].tezInfo = getHaveBao(funTopar, [evalCmd, renWu, coLid, intOfJs], 1, yhhDict[coLid].commentOfme[2], yhhDict[coLid].commentOfme[4])


                funTopar = path.findParent(function (p) {
                    if (p.isBlockStatement()) {
                        return true;
                    }
                });

                funTopar.traverse({
                    Identifier(p) {
                        findBiianLian += 1
                        if (p.node.name == intOfJs && (p.parentPath + '') == hans) {
                            findBiianLian -= 1
                            p.stop()
                        } else if (p.node.name == intOfJs) {
                            ncv.push(findBiianLian)
                        }
                        ;
                    }
                });
                yhhDict[coLid].commentOfme.push(ncv[ncv.length - 1])
                yhhDict[coLid].tezBlock = getHaveBao(funTopar, [evalCmd, renWu, coLid, intOfJs], 0, yhhDict[coLid].commentOfme[2], yhhDict[coLid].commentOfme[4])
                //这里是输出了函数的特征
                funTopar = path.findParent(function (p) {
                    if (p.isBlockStatement()) {
                        return true;
                    }
                });


            })
        }

        if (haveIn.length == lenAbot) {
            // Ident Numb Strig 兄弟节点 IntSum func结构
            getBianlian = [0, 0, 0, 0, 0, ''];
            var yhh = 0
            path.traverse({
                Identifier(path) {
                    if (path.node.name == 'cbbiyhh') {
                        return;
                    }
                    getBianlian[0] += 1;
                    if (yhh == 0) {
                        yhh = 1
                        let body = path.find((p) => eval('p.is' + findType + '()')).node.body.body
                        if (body == undefined) {
                            return;
                        }
                        let openju = body.length;
                        body.forEach(function (x) {
                            if (generator(x).code.slice(0, 11) == 'var cbbiyhh' || generator(x).code.slice(0, 7) == 'cbbiyhh') {
                                openju -= 1;
                                return;
                            }
                            getBianlian[5] += x.type[0]
                        })
                        getBianlian[3] = openju;


                    }

                },
                NumericLiteral(path) {
                    getBianlian[1] += 1
                    // getBianlian[4] += path.node.value
                },
                StringLiteral(path) {
                    if ((path.parentPath + "").indexOf('cbbiyhh') != -1) {
                        return;
                    }
                    getBianlian[2] += 1
                }

            })
            getKf.push(listSt.concat(getBianlian).join('-'))
        }
        ;
    }

    const getKf = [];

    var getBianlian = [];

    function getHaveBao(funTopar, evalCmd, id, typeOf, rr) {
        if (id == 1) {
            var listIdof = ['', '', 0, '', -1]
            funTopar.node.params.forEach((x) => {
                listIdof[3] += x.type[0]
            })
        } else {
            var listIdof = ['', '', 0, '', -1]
        }
        ;

        var jinrcis = 0
        var cbbYhh = {
            NumericLiteral(pat) {
                listIdof[0] += pat.node.value;
            },
            StringLiteral(pat) {
                if (evalCmd.indexOf(pat.node.value) == -1) {
                    listIdof[1] += pat.node.value;
                }
            },
            Identifier(pat) {
                if (pat.node.name != 'cbbiyhh') {
                    listIdof[2] += 1;
                }
            },
        }
        cbbYhh[typeOf] = function (pat) {
            if ((pat + '') == rr) {
                listIdof[4] = jinrcis
            }
            jinrcis += 1
        }
        funTopar.traverse(cbbYhh);
        return listSt.concat(listIdof);
    };

    const getAstFunc = (pathParent) => {

        pathParent.traverse({
            FunctionExpression(path) {
                cbb()
                let lenAbot = haveIn.length
                getAstFunc(path);
                cbbl(path, lenAbot, "FunctionExpression")
                letbeRuue -= 1
                path.skip()
            },
            ArrowFunctionExpression(path) {
                cbb()
                let lenAbot = haveIn.length
                getAstFunc(path);
                cbbl(path, lenAbot, "ArrowFunctionExpression")
                letbeRuue -= 1
                path.skip()
            }, FunctionDeclaration(path) {
                cbb()
                let lenAbot = haveIn.length
                getAstFunc(path);
                cbbl(path, lenAbot, "FunctionDeclaration")
                letbeRuue -= 1
                path.skip()
            },
        })
    }

    const astGet = {
        FunctionExpression(path) {
            cbb()
            getAstFunc(path);
            letbeRuue -= 1
            path.skip()
        },
        ArrowFunctionExpression(path) {
            cbb()
            getAstFunc(path);
            letbeRuue -= 1
            path.skip()
        },
        FunctionDeclaration(path) {

            if (path.node.id.name == "vs") {
                debugger;
            }
            cbb()
            getAstFunc(path);
            letbeRuue -= 1
            path.skip()
        },
    };


    traverse(ast, astGet);
    wordListOfCbb.push(yhhDict)
    console.log(listSt)
    return {'JSfeatures': JSfeatures, 'listSt': listSt, 'getKf': getKf, 'wordListOfCbb': wordListOfCbb}
}


let fileOfJs = fs.readdirSync('cySearsh')
wordListOfCbb = []
console.log(fileOfJs)


var JSfeaturesList = []
var listStList = []
var getKfList = []


for (i in fileOfJs) {
    var text = fs.readFileSync('./cySearsh/' + fileOfJs[i], {encoding: "utf8"})
    let dataDist = main(text, i);
    JSfeaturesList.push(dataDist['JSfeatures'])
    listStList.push(dataDist['listSt'])
    getKfList.push(dataDist['getKf'])
}

function getInofnm() {
    var listStListall = [];
    var isTrue2 = listStList[0].length;
    var oplength = listStList.length;
    for (var i = 0; i < isTrue2; i++) {
        var setOfit = [];
        for (var i2 = 0; i2 < oplength; i2++) {
            setOfit.push(listStList[i2][i]);
        }
        ;
        var yhh = new Set(setOfit);
        if (yhh.size != 1) {
            listStListall.push(0);
        } else {
            listStListall.push(1);
        }
        ;
    }
    ;
    return listStListall;
};


function getInofnm2(listStList) {
    var listStListall = [[], []];
    for (var idf = 0; idf < 2; idf++) {
        var isTrue2 = listStList[idf][idf].length;
        var oplength = listStList.length;
        for (var i = 0; i < isTrue2; i++) {
            var setOfit = [];
            for (var i2 = 0; i2 < oplength; i2++) {
                setOfit.push(listStList[i2][idf][i]);
            }
            ;
            var yhh = new Set(setOfit);
            if (yhh.size != 1) {
                listStListall[idf].push(0);
            } else {
                listStListall[idf].push(1);
            }
            ;
        }
        ;
    }
    return listStListall;
};

function getdata() {
    var FunctionDeclarationall = 1;
    var isTrue = JSfeaturesList[0].cbbFunctionDeclaration
    JSfeaturesList.forEach((p) => {
        if (p.cbbFunctionDeclaration != isTrue) {
            FunctionDeclarationall = 0;
        }
        ;
    });

    var listStListall = getInofnm();

    var getKfListall = [];
    var isHavegetKf = new Set(getKfList[0]);
    for (i = 0; i < getKfList.length; i++) {
        isHavegetKf = havegetKf(getKfList[i], isHavegetKf);
    }

    var wordListOfCbball = {};
    var keyOfword = Object.keys(wordListOfCbb[0])

    for (iw in keyOfword) {
        var tezInfolist = []
        var tezBlocklist = []
        var quFun = [];
        var quBla = [];
        var kop = [[], [], [], [], []]
        for (i = 0; i < wordListOfCbb.length; i++) {
            tezInfolist.push([wordListOfCbb[i][keyOfword[iw]].tezInfo.slice(0, wordListOfCbb[i][keyOfword[iw]].tezInfo.length - 5), wordListOfCbb[i][keyOfword[iw]].tezInfo.slice(wordListOfCbb[i][keyOfword[iw]].tezInfo.length - 5, wordListOfCbb[i][keyOfword[iw]].tezInfo.length - 1)]);
            tezBlocklist.push([wordListOfCbb[i][keyOfword[iw]].tezBlock.slice(0, wordListOfCbb[i][keyOfword[iw]].tezBlock.length - 5), wordListOfCbb[i][keyOfword[iw]].tezBlock.slice(wordListOfCbb[i][keyOfword[iw]].tezBlock.length - 5, wordListOfCbb[i][keyOfword[iw]].tezBlock.length - 1)]);
            quFun.push(wordListOfCbb[i][keyOfword[iw]].commentOfme[5])
            quBla.push(wordListOfCbb[i][keyOfword[iw]].commentOfme[6])
            wordListOfCbb[i][keyOfword[iw]].commentOfme.pop()
            wordListOfCbb[i][keyOfword[iw]].commentOfme.pop()
            kop[0].push(wordListOfCbb[i][keyOfword[iw]].commentOfme[0])
            kop[1].push(wordListOfCbb[i][keyOfword[iw]].commentOfme[1])
            kop[2].push(wordListOfCbb[i][keyOfword[iw]].commentOfme[2])
            kop[3].push(wordListOfCbb[i][keyOfword[iw]].commentOfme[3])
            kop[4].push(wordListOfCbb[i][keyOfword[iw]].commentOfme[4])
        }
        var jkll = getInofnm2(tezInfolist);
        console.log(jkll);
        var jkll2 = getInofnm2(tezBlocklist);
        console.log(jkll2);
        let zsi = [[], []]
        if (new Set(quFun).size == 1) {
            zsi[0].push(quFun[0]);
            zsi[0].push(1);
        } else {
            zsi[0].push(0);
            zsi[0].push(0);

        }
        ;
        if (new Set(quBla).size == 1) {
            zsi[1].push(quBla[0]);
            zsi[1].push(1);
        } else {
            zsi[1].push(0);
            zsi[1].push(0);

        }
        ;
        let pkkk = wordListOfCbb[0][keyOfword[iw]].commentOfme
        let pkTz = []
        for (let i = 0; i < kop.length; i++) {
            if (new Set(kop[i]).size == 1) {
                pkTz.push(1)
            } else {
                pkTz.push(0)
            }
        }

        wordListOfCbball[keyOfword[iw]] = [[tezInfolist[0], tezBlocklist[0]], [jkll, jkll2], wordListOfCbb[0][keyOfword[iw]].evalCmd, zsi, [pkkk, pkTz]];

    }
    ;


    return {
        // 函数数量
        'firstCbb': [isTrue, FunctionDeclarationall],
        // 函数结构已经相同位置
        'andYhh': [listStList[0], listStListall],
        // 最末结构
        'lastZcj': Array.from(isHavegetKf),
        // 特征位置定位
        'every': wordListOfCbball
    };
}

function havegetKf(getKf, isHavegetKf) {
    return new Set([...getKf].filter(x => isHavegetKf.has(x)))
}

let dataOfJs = getdata()

fs.writeFile("./jstz.txt", JSON.stringify(dataOfJs), (err) => {
})

console.log(JSON.stringify(dataOfJs))
// console.log(JSON.stringify(wordListOfCbb))



